Namespace Utility

    ''' <summary>
    ''' Object serialize utility.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class Serializer
        Inherits Object

        ''' <summary>
        ''' Serialize the target object into the file.
        ''' </summary>
        ''' <param name="Target">Target instance to serialize.</param>
        ''' <param name="FileName">Serialized file path and name.</param>
        ''' <param name="Overwrite">Set the file will be overwrited when existed.</param>
        ''' <remarks></remarks>
        Public Shared Sub Serialize(ByVal Target As Object, ByVal FileName As String, ByVal Overwrite As Boolean)
            Dim formatter As Runtime.Serialization.IFormatter
            If Target Is Nothing Then
                Throw New NullReferenceException
            Else
                If IO.File.Exists(FileName) = True AndAlso Overwrite = False Then
                    Throw New FileExistException(FileName)
                Else
                    If Target.GetType.IsSerializable = True Then
                        formatter = New Runtime.Serialization.Formatters.Binary.BinaryFormatter
                        Using stream As New IO.FileStream(FileName, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
                            formatter.Serialize(stream, Target)
                        End Using
                    Else
                        Throw New CannotSerializeException(Target)
                    End If
                End If
            End If
        End Sub

        ''' <summary>
        ''' Load the serialization file and translate into instance.
        ''' </summary>
        ''' <param name="FileName">File path and name.</param>
        ''' <returns>Object instance be deserialized.</returns>
        ''' <remarks></remarks>
        Public Shared Function Deserialize(ByVal FileName As String) As Object
            Dim ret As Object = Nothing
            Dim formatter As Runtime.Serialization.IFormatter
            If IO.File.Exists(FileName) = True Then
                formatter = New Runtime.Serialization.Formatters.Binary.BinaryFormatter
                Using stream As New IO.FileStream(FileName, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
                    ret = formatter.Deserialize(stream)
                End Using
            Else
                Throw New IO.FileNotFoundException(FileName & " is not found.", FileName)
            End If
            Return ret
        End Function

#Region " Exception Classes "

        ''' <summary>
        ''' File has been exist exception.
        ''' </summary>
        ''' <remarks></remarks>
        Public Class FileExistException
            Inherits Exception

            Private m_fileName As String

            ''' <summary>
            ''' Get the file name.
            ''' </summary>
            ''' <value></value>
            ''' <returns>The file name.</returns>
            ''' <remarks></remarks>
            Public ReadOnly Property FileName() As String
                Get
                    Return m_fileName
                End Get
            End Property

            ''' <summary>
            ''' Create instance.
            ''' </summary>
            ''' <param name="FileName">The name that is exist.</param>
            ''' <remarks></remarks>
            Public Sub New(ByVal FileName As String)
                MyBase.New(FileName & " is existed.")
                m_fileName = FileName
            End Sub

        End Class

        ''' <summary>
        ''' Can not serialization exception.
        ''' </summary>
        ''' <remarks></remarks>
        Public Class CannotSerializeException
            Inherits Exception

            Private m_innerObj As Object

            ''' <summary>
            ''' Get the type that can not be serialized instance.
            ''' </summary>
            ''' <value></value>
            ''' <returns>The type that can not be serialized instance.</returns>
            ''' <remarks></remarks>
            Public ReadOnly Property Type() As Type
                Get
                    Return m_innerObj.GetType
                End Get
            End Property

            ''' <summary>
            ''' Get the instance that can not be serialized instance.
            ''' </summary>
            ''' <value></value>
            ''' <returns>The instance that can not be serialized instance.</returns>
            ''' <remarks></remarks>
            Public ReadOnly Property [Object]() As Object
                Get
                    Return m_innerObj
                End Get
            End Property

            ''' <summary>
            ''' Create instance.
            ''' </summary>
            ''' <param name="obj">Can not be sreialized instance.</param>
            ''' <remarks></remarks>
            Public Sub New(ByVal obj As Object)
                MyBase.New(obj.GetType.FullName & " cannot be serialize.")
                m_innerObj = obj
            End Sub
        End Class

#End Region

    End Class

End Namespace
